/**
 * 实现以下几个方法
 * define全局方法
 * require全局方法
 * rj全局对象
 */
const def = new Map();
const defaultOptions = {
  paths: '',
};

// 加载cdn链接
const __import = (url) => {
  return new Promise((resolve, reject) => {
    // eslint-disable-next-line no-restricted-properties
    window.System.import(url).then(resolve, reject);
  });
};

const __load = (url) => {
  return new Promise((r, reject) => {
    /* const head = document.getElementsByTagName('head')[0];
    const srciptDom = document.createElement('script');
    srciptDom.url = url;
    srciptDom.type = 'text/javascript';
    srciptDom.async = true;
    srciptDom.onload = r;
    srciptDom.onerror = reject;
    head.appendChild(srciptDom); */
    const head = document.getElementsByTagName('head')[0];
    const node = document.createElement('script');
    node.type = 'text/javascript';
    node.src = url;
    node.async = true;
    node.onload = r;
    node.onerror = reject;
    head.appendChild(node);
  });
};

const __getUrl = (name) => {
  // eslint-disable-next-line no-restricted-globals
  const pathname = location.pathname;
  return pathname.slice(0, pathname.lastIndexOf('/')) + '/' + name + '.js';
};
// 加载javascript文件

window.rj = {
  config: function (options) {
    return Object.assign(defaultOptions, options);
  },
};

// 依赖收集
window.define = function (name, deps, factory) {
  def.set(name, {
    name,
    deps,
    factory,
  });
};
/* 
  返回值：返回deps依赖对应的模块数组
*/
window.require1 = (deps, factory) => {
  return new Promise((resolve, reject) => {
    deps = deps || [];
    Promise.all(
      deps.map((dep) => {
        // 加载外链
        if (defaultOptions.paths[dep]) {
          return __import(defaultOptions.paths[dep]);
        }
        return __load(__getUrl(dep)).then(() => {
          // 已经加载完define定义的模块了
          const { deps, factory } = def.get(dep);
          if (!deps || deps.length === 0) {
            return factory(null);
          }
          return require(deps, factory);
        });
      })
    ).then(resolve, reject);
  }).then((instances) => {
    console.log('instances', instances);
    return factory(...instances);
  });
};
// 其实才是触发加载依赖的地方
require2 = (deps, factory) => {
  return new Promise((resolve, reject) => {
    Promise.all(
      deps.map((dep) => {
        // 走 CDN
        if (defaultOptions.paths[dep])
          return __import(defaultOptions.paths[dep]);

        return __load(__getUrl(dep)).then(() => {
          const { deps, factory } = def.get(dep);
          if (deps.length === 0) return factory(null);
          return require(deps, factory);
        });
      })
    ).then(resolve, reject);
  }).then((instances) => factory(...instances));
};

// 返回加载模块后的值
window.require = function (deps, factory) {
  return new Promise((resolve, reject) => {
    Promise.all(
      deps.map((dep) => {
        // cdn模块
        if (defaultOptions.paths[dep])
          return __import(defaultOptions.paths[dep]);
        return __load(__getUrl(dep)).then(() => {
          const { deps, factory } = def.get(dep);
          if (!deps.length) {
            return factory();
          }
          return require(deps, factory);
        });
      })
    ).then(resolve, reject);
  }).then((deps) => factory(...deps));
};
/* 
  require加载模块是依赖前置的形式，必须加载所有的模块后，才会去执行factory方法，并传入加载好的模块
*/
